package com.example.kotlin

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Backspace
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.kotlin.ui.theme.KotlintestTheme
import androidx.compose.material3.ExperimentalMaterial3Api

/**
 * CalculatorActivity - 计算器应用
 *
 * 这是一个完整的计算器实现，展示了Kotlin和Jetpack Compose的核心概念
 *
 * 学习要点：
 * 1. 状态管理（State Management）- 使用remember和mutableStateOf
 * 2. 组合函数（Composable Functions）- 声明式UI构建
 * 3. 事件处理（Event Handling）- 按钮点击响应
 * 4. 布局系统（Layout System）- Column、Row、Box等布局组件
 * 5. 字符串处理（String Processing）- Kotlin的字符串操作
 * 6. 异常处理（Exception Handling）- try-catch块
 *
 * 注意事项：
 * - 本计算器使用eval-like的方式计算表达式
 * - 在实际生产环境中，建议使用专业的表达式解析库
 * - 需要处理除零错误等边界情况
 */
class CalculatorActivity : ComponentActivity() {

    /**
     * onCreate生命周期方法
     *
     * 这是Activity的入口点，在Activity创建时被系统调用
     */
    @OptIn(ExperimentalMaterial3Api::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            KotlintestTheme {
                Scaffold(
                    modifier = Modifier.fillMaxSize(),
                    topBar = {
                        // 添加顶部导航栏和返回按钮
                        TopAppBar(
                            title = { Text("计算器") },
                            navigationIcon = {
                                IconButton(onClick = { finish() }) {
                                    Icon(
                                        imageVector = Icons.Filled.ArrowBack,
                                        contentDescription = "返回"
                                    )
                                }
                            }
                        )
                    }
                ) { innerPadding ->
                    // 显示计算器主界面
                    CalculatorScreen(modifier = Modifier.padding(innerPadding))
                }
            }
        }
    }
}

/**
 * CalculatorScreen - 计算器主屏幕组件
 *
 * 这是计算器的主UI组件，包含显示屏和按键布局
 *
 * @param modifier 修饰符，用于外部调整样式
 *
 * 关键概念：
 * - remember - 在重组（recomposition）时保持状态
 * - mutableStateOf - 创建可观察的状态，状态改变会触发UI重组
 * - by关键字 - Kotlin的属性委托语法，简化状态读写
 */
@Composable
fun CalculatorScreen(modifier: Modifier = Modifier) {
    /**
     * 状态管理
     *
     * displayText - 显示屏显示的内容
     * currentInput - 当前输入的数字或表达式
     *
     * remember { mutableStateOf("") }：
     * - remember: 在重组时记住这个值，避免状态丢失
     * - mutableStateOf: 创建可变状态，改变时会触发UI更新
     * - by关键字: 使用属性委托，可以直接读写值，而不需要.value
     *
     * 注意事项：
     * - 不使用remember会导致每次重组都重置状态
     * - 不使用mutableStateOf会导致UI不更新
     */
    var displayText by remember { mutableStateOf("0") }
    var currentInput by remember { mutableStateOf("") }
    var lastResult by remember { mutableStateOf<Double?>(null) }

    /**
     * Column布局 - 垂直排列子元素
     *
     * modifier属性：
     * - fillMaxSize() - 填充整个屏幕
     * - background() - 设置背景色
     * - padding() - 设置内边距
     */
    Column(
        modifier = modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .padding(16.dp)
    ) {
        /**
         * 显示屏区域
         *
         * weight(1f) - 占据剩余空间
         * - 这样可以让按键区域固定大小，显示屏自适应
         */
        CalculatorDisplay(
            text = displayText,
            modifier = Modifier
                .fillMaxWidth()
                .weight(1f)
        )

        Spacer(modifier = Modifier.height(16.dp))

        /**
         * 按键区域
         *
         * onButtonClick是一个lambda函数，处理所有按钮的点击事件
         * when表达式是Kotlin的强大特性，类似Java的switch但更强大
         */
        CalculatorButtons(
            onButtonClick = { button ->
                when (button) {
                    // 清除按钮 - 重置所有状态
                    "C" -> {
                        displayText = "0"
                        currentInput = ""
                        lastResult = null
                    }

                    // 退格按钮 - 删除最后一个字符
                    "⌫" -> {
                        if (currentInput.isNotEmpty()) {
                            currentInput = currentInput.dropLast(1)
                            displayText = currentInput.ifEmpty { "0" }
                        }
                    }

                    // 等号按钮 - 计算结果
                    "=" -> {
                        try {
                            // 计算表达式
                            val result = evaluateExpression(currentInput)
                            lastResult = result
                            // 格式化结果（去除不必要的小数点）
                            displayText = formatResult(result)
                            currentInput = displayText
                        } catch (e: Exception) {
                            // 异常处理 - 显示错误信息
                            displayText = "错误"
                            currentInput = ""
                        }
                    }

                    // 运算符和数字按钮
                    else -> {
                        // 如果显示"错误"，先清除
                        if (displayText == "错误") {
                            currentInput = ""
                        }

                        // 处理首次输入或新计算
                        if (currentInput.isEmpty() && displayText == "0") {
                            currentInput = button
                        } else {
                            currentInput += button
                        }

                        displayText = currentInput
                    }
                }
            }
        )
    }
}

/**
 * CalculatorDisplay - 计算器显示屏组件
 *
 * 显示当前的计算表达式或结果
 *
 * @param text 要显示的文本
 * @param modifier 修饰符
 *
 * 设计说明：
 * - 使用Card组件提供视觉层次感
 * - 右对齐文本，符合计算器的习惯
 * - 支持多行显示，确保长表达式完整可见
 */
@Composable
fun CalculatorDisplay(
    text: String,
    modifier: Modifier = Modifier
) {
    /**
     * Card组件 - Material Design卡片
     *
     * colors参数设置卡片的颜色方案
     * - containerColor: 卡片背景色
     * - 使用surfaceVariant提供视觉区分
     */
    Card(
        modifier = modifier,
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surfaceVariant
        ),
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
    ) {
        /**
         * Column布局 - 垂直布局，从底部对齐
         *
         * verticalArrangement - 垂直排列方式
         * Bottom - 从底部开始排列，确保文本贴底显示
         */
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp),
            verticalArrangement = Arrangement.Bottom,
            horizontalAlignment = Alignment.End
        ) {
            /**
             * Text组件 - 显示文本
             *
             * 属性说明：
             * - fontSize: 字体大小，使用sp单位（可缩放像素）
             * - fontWeight: 字体粗细
             * - textAlign: 文本对齐方式
             * - color: 文本颜色
             * - lineHeight: 行高，确保多行文本有足够间距
             */
            Text(
                text = text,
                fontSize = 48.sp,
                fontWeight = FontWeight.Bold,
                textAlign = TextAlign.End,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                lineHeight = 56.sp,
                modifier = Modifier.fillMaxWidth()
            )
        }
    }
}

/**
 * CalculatorButtons - 计算器按键布局组件
 *
 * 定义计算器的所有按键布局和样式
 *
 * @param onButtonClick 按钮点击回调函数
 *
 * 布局说明：
 * - 5行按键（数字、运算符、功能键）
 * - 使用Grid布局实现均匀分布
 * - 不同类型按钮使用不同颜色区分
 */
@Composable
fun CalculatorButtons(
    onButtonClick: (String) -> Unit
) {
    /**
     * 按键定义
     *
     * listOf创建按键行列表
     * 每一行是一个List<String>，包含该行的所有按键
     *
     * 布局说明：
     * 第1行: C, ⌫, %, ÷
     * 第2行: 7, 8, 9, ×
     * 第3行: 4, 5, 6, -
     * 第4行: 1, 2, 3, +
     * 第5行: 0, ., =
     */
    val buttons = listOf(
        listOf("C", "⌫", "%", "÷"),
        listOf("7", "8", "9", "×"),
        listOf("4", "5", "6", "-"),
        listOf("1", "2", "3", "+"),
        listOf("0", ".", "=")
    )

    /**
     * Column布局 - 垂直排列按键行
     *
     * verticalArrangement - 设置垂直间距
     * spacedBy(8.dp) - 每行之间间隔8dp
     */
    Column(
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        /**
         * forEach循环 - 遍历每一行按键
         *
         * Kotlin的集合操作非常简洁
         * row是lambda参数，代表当前行
         */
        buttons.forEach { row ->
            /**
             * Row布局 - 水平排列按键
             *
             * horizontalArrangement - 设置水平间距
             * Modifier.weight(1f) - 每个按钮等宽
             */
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                row.forEach { buttonText ->
                    /**
                     * 根据按钮类型选择颜色
                     *
                     * when表达式返回值
                     * in关键字检查元素是否在集合中
                     *
                     * 颜色方案：
                     * - 数字和小数点：primary（主色）
                     * - 运算符：secondary（辅助色）
                     * - 功能键：tertiary（第三色）
                     */
                    val buttonColor = when (buttonText) {
                        in listOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".") ->
                            MaterialTheme.colorScheme.primary

                        in listOf("+", "-", "×", "÷", "%", "=") ->
                            MaterialTheme.colorScheme.secondary

                        else -> MaterialTheme.colorScheme.tertiary
                    }

                    // 绘制单个按钮
                    CalculatorButton(
                        text = buttonText,
                        onClick = { onButtonClick(buttonText) },
                        backgroundColor = buttonColor,
                        modifier = Modifier
                            .weight(1f)
                            .aspectRatio(1f) // 保持按钮为正方形
                    )
                }
            }
        }
    }
}

/**
 * CalculatorButton - 单个计算器按钮组件
 *
 * 可复用的按钮组件，定义了按钮的外观和行为
 *
 * @param text 按钮显示的文本
 * @param onClick 点击事件回调
 * @param backgroundColor 背景颜色
 * @param modifier 修饰符
 *
 * 设计说明：
 * - 使用FilledTonalButton提供Material Design风格
 * - 圆形形状（CircleShape）更美观
 * - 大字体，方便点击
 */
@Composable
fun CalculatorButton(
    text: String,
    onClick: () -> Unit,
    backgroundColor: Color,
    modifier: Modifier = Modifier
) {
    /**
     * FilledTonalButton - Material Design 3的按钮
     *
     * 特点：
     * - 填充式按钮，有背景色
     * - 自动处理点击涟漪效果
     * - 支持无障碍功能
     *
     * colors参数：
     * - containerColor: 按钮背景色
     * - contentColor: 按钮内容（文字）颜色
     *
     * shape参数：
     * - CircleShape: 圆形形状
     */
    FilledTonalButton(
        onClick = onClick,
        modifier = modifier,
        colors = ButtonDefaults.filledTonalButtonColors(
            containerColor = backgroundColor,
            contentColor = MaterialTheme.colorScheme.onPrimary
        ),
        shape = CircleShape,
        contentPadding = PaddingValues(0.dp)
    ) {
        /**
         * 按钮内容
         *
         * 特殊处理退格图标，其他显示文本
         */
        if (text == "⌫") {
            // 使用Material图标表示退格
            Icon(
                imageVector = Icons.Filled.Backspace,
                contentDescription = "删除",
                modifier = Modifier.size(28.dp)
            )
        } else {
            // 显示文本
            Text(
                text = text,
                fontSize = 24.sp,
                fontWeight = FontWeight.Bold
            )
        }
    }
}

/**
 * evaluateExpression - 表达式求值函数
 *
 * 将字符串表达式转换为数学结果
 *
 * @param expression 数学表达式字符串（如 "3+5*2"）
 * @return 计算结果
 * @throws ArithmeticException 除零异常
 * @throws NumberFormatException 格式错误异常
 *
 * 实现说明：
 * - 使用简单的递归下降解析器
 * - 支持+、-、×、÷、%运算符
 * - 遵循标准数学运算优先级（先乘除后加减）
 *
 * 注意事项：
 * - 这是一个简化实现，实际生产环境建议使用专业的表达式解析库
 * - 不支持括号运算
 * - 不支持负数开头（可以改进）
 */
fun evaluateExpression(expression: String): Double {
    // 空字符串返回0
    if (expression.isEmpty()) return 0.0

    /**
     * 替换显示用的运算符为标准运算符
     *
     * replace函数：
     * - 第一个参数：要查找的字符串
     * - 第二个参数：替换成的字符串
     * - 返回新字符串，原字符串不变
     */
    val sanitized = expression
        .replace("×", "*")
        .replace("÷", "/")

    /**
     * 解析表达式
     *
     * try-catch块：
     * - try中的代码可能抛出异常
     * - catch捕获异常并处理
     * - 可以有多个catch块捕获不同类型的异常
     */
    return try {
        // 简单实现：将表达式按运算符分割并计算
        evaluateSimpleExpression(sanitized)
    } catch (e: Exception) {
        throw ArithmeticException("计算错误")
    }
}

/**
 * evaluateSimpleExpression - 简单表达式求值
 *
 * 实现基本的四则运算，支持运算符优先级
 *
 * @param expression 表达式字符串
 * @return 计算结果
 *
 * 算法说明：
 * 1. 先处理加法和减法（拆分表达式）
 * 2. 再处理乘法和除法（递归处理）
 * 3. 最后处理数字（基础情况）
 *
 * 例子：
 * "3+5*2" -> 3 + (5*2) -> 3 + 10 -> 13
 */
private fun evaluateSimpleExpression(expression: String): Double {
    // 去除空格
    val exp = expression.replace(" ", "")

    // 处理加法
    if (exp.contains("+")) {
        val parts = exp.split("+")
        return parts.map { evaluateSimpleExpression(it) }.sum()
    }

    // 处理减法
    if (exp.contains("-") && !exp.startsWith("-")) {
        val parts = exp.split("-")
        var result = evaluateSimpleExpression(parts[0])
        for (i in 1 until parts.size) {
            result -= evaluateSimpleExpression(parts[i])
        }
        return result
    }

    // 处理乘法
    if (exp.contains("*")) {
        val parts = exp.split("*")
        return parts.map { evaluateSimpleExpression(it) }.reduce { acc, d -> acc * d }
    }

    // 处理除法
    if (exp.contains("/")) {
        val parts = exp.split("/")
        var result = evaluateSimpleExpression(parts[0])
        for (i in 1 until parts.size) {
            val divisor = evaluateSimpleExpression(parts[i])
            if (divisor == 0.0) {
                throw ArithmeticException("除数不能为零")
            }
            result /= divisor
        }
        return result
    }

    // 处理取模
    if (exp.contains("%")) {
        val parts = exp.split("%")
        return evaluateSimpleExpression(parts[0]) % evaluateSimpleExpression(parts[1])
    }

    // 基础情况：纯数字
    return exp.toDouble()
}

/**
 * formatResult - 格式化结果显示
 *
 * 将Double类型的结果转换为易读的字符串
 *
 * @param result 计算结果
 * @return 格式化后的字符串
 *
 * 格式化规则：
 * - 如果是整数，去掉小数点（如 5.0 -> 5）
 * - 如果是小数，保留小数点（如 5.5 -> 5.5）
 * - 限制小数位数，避免浮点精度问题
 */
fun formatResult(result: Double): String {
    /**
     * % 操作符 - 取模运算
     * result % 1 == 0.0 表示result是整数
     *
     * 例子：
     * 5.0 % 1 = 0.0 (整数)
     * 5.5 % 1 = 0.5 (小数)
     */
    return if (result % 1 == 0.0) {
        // 整数：转换为Long去掉小数部分
        result.toLong().toString()
    } else {
        /**
         * String.format - 格式化字符串
         *
         * "%.8f" 表示：
         * - %: 格式化标记
         * - .8: 保留8位小数
         * - f: 浮点数类型
         *
         * trimEnd('0') - 去掉末尾的0
         * trimEnd('.') - 去掉末尾的小数点
         */
        String.format("%.8f", result)
            .trimEnd('0')
            .trimEnd('.')
    }
}

/**
 * Preview预览函数
 *
 * 在Android Studio中显示组件预览
 * 无需运行应用即可查看UI效果
 */
@Preview(showBackground = true)
@Composable
fun CalculatorScreenPreview() {
    KotlintestTheme {
        CalculatorScreen()
    }
}
